#include "OffLineRenderPCH.h"
#include "OR_SamplerHalton.h"


using namespace OffLineRender;
using namespace Utility;
//-------------------------------------------------------------------
OR_SamplerHalton::OR_SamplerHalton(int xs, int xe, int ys, int ye, int ps,float sopen, float sclose)
	: OR_SamplerBase(xs, xe, ys, ye, ps, sopen, sclose) 
{
	int delta = UT_MathHelper::Max(m_iXPixelEnd - m_iXPixelStart,m_iYPixelEnd - m_iYPixelStart);
	m_iWantedSamples = m_iSamplesPerPixel * delta * delta;
	m_iCurrentSample = 0;
}
//-------------------------------------------------------------------
int OR_SamplerHalton::GenerateSamples(OR_Sample *sample, Utility::UT_RandomNumGenerator &rng)
{
retry:
	if (m_iCurrentSample >= m_iWantedSamples)
		return 0;

	// Generate sample with Halton sequence and reject if outside image extent
	float u = (float)UT_SampleHelper::RadicalInverse(m_iCurrentSample, 3);
	float v = (float)UT_SampleHelper::RadicalInverse(m_iCurrentSample, 2);
	float lerpDelta = float(UT_MathHelper::Max(m_iXPixelEnd - m_iXPixelStart,m_iYPixelEnd - m_iYPixelStart));
	
	sample->m_fImageX = UT_MathHelper::Lerp(u, m_iXPixelStart, m_iXPixelStart + lerpDelta);
	sample->m_fImageY = UT_MathHelper::Lerp(v, m_iYPixelStart, m_iYPixelStart + lerpDelta);
	
	++m_iCurrentSample;

	if (sample->m_fImageX >= m_iXPixelEnd || sample->m_fImageY >= m_iYPixelEnd)
		goto retry;

	// Generate lens, time, and integrator samples for _HaltonSampler_
	sample->m_fLensU = (float)UT_SampleHelper::RadicalInverse(m_iCurrentSample, 5);
	sample->m_fLensV = (float)UT_SampleHelper::RadicalInverse(m_iCurrentSample, 7);
	sample->m_fTime  = UT_MathHelper::Lerp((float)UT_SampleHelper::RadicalInverse(m_iCurrentSample, 11),m_fShutterOpenTime, m_fShutterCloseTime);
	
	for (uint32_t j = 0; j < sample->m_k1DNumVector.GetSize(); ++j)
		UT_SampleHelper::SampleLatinHypercube(sample->m_pp1DData[j], sample->m_k1DNumVector.GetAt(j), 1, rng);

	for (uint32_t j = 0; j < sample->m_k2DNumVector.GetSize(); ++j)
		UT_SampleHelper::SampleLatinHypercube(sample->m_pp2DData[j], sample->m_k2DNumVector.GetAt(j), 2, rng);

	return 1;
}
//-------------------------------------------------------------------
OR_SamplerBase *OR_SamplerHalton::GetSubSampler(int num, int count)
{
	int x0, x1, y0, y1;
	_computeSubWindow(num, count, &x0, &x1, &y0, &y1);
	if (x0 == x1 || y0 == y1)
		return NULL;
	
	return new OR_SamplerHalton(x0, x1, y0, y1, m_iSamplesPerPixel, m_fShutterOpenTime,m_fShutterCloseTime);
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------